home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
endo
/
plot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
10KB
|
252 lines
/*************************************************************************
* *
* Copyright (c) 1992, 1993 Ronald Joe Record *
* *
* All rights reserved. No part of this program or publication may be *
* reproduced, transmitted, transcribed, stored in a retrieval system, *
* or translated into any language or computer language, in any form or *
* by any means, electronic, mechanical, magnetic, optical, chemical, *
* biological, or otherwise, without the prior written permission of: *
* *
* Ronald Joe Record (408) 458-3718 *
* 212 Owen St., Santa Cruz, California 95062 USA *
* *
*************************************************************************/
/***************************************************************************
* *
* Copyright (c) 1989 Hiram Clawson *
* *
* All rights reserved. No part of this program or publication may be *
* reproduced, transmitted, transcribed, stored in a retrieval system, *
* or translated into any language or computer language, in any form or *
* by any means, electronic, mechanical, magnetic, optical, chemical, *
* biological, or otherwise, without the prior written permission of: *
* *
* Hiram Clawson (408) 429-5647 *
* P. O. Box 3178, Santa Cruz, California 95063-3178 USA *
* *
***************************************************************************/
/***************************************************************************
* plot.c: Plot a 3D point through a window in 3D space that *
* is the computer display screen. *
* *
* Written by Hiram Clawson. *
* Ported to X11 by Ronald Joe Record. *
***************************************************************************/
#include "globals.h"
int plot( _3D_point, _2D_point ) /* returns TRUE when on screen */
triple _3D_point;
xy_t *_2D_point;
{
/*
* Given a point in 3D space: _3D_point.x, _3D_point.y, _3D_point.z
* and a screen center of (screen_center.x, screen_center.y)
* (upper left is 0,0), lower right is (screen_max.x,screen_max.y)
* (lower left is 0,0), upper right is (screen_max.x,screen_max.y)
*
* return plot point _2D_point->x, _2D_point->y as seen through a window
* from the viewpoint (view_point.x, view_point.y, view_point.z)
*
* The window is an arbitary plane in x,y,z space defined by four points:
* window center (window_center.x, .y, .z)
* top middle of window (window_top.x, .y, .z)
* right middle (window_right.x, .y, .z)
* upper right window corner(window_upper_right.x, .y, .z)
*
* The viewpoint is on a perpendicular (to the window plane) line through
* the center to the window.
*
* There are some global constants floating around that were set up by
* view_point_constants concerning the window. When the window
* is moved they are recomputed by view_point_constants.
* They are vectors associated with the window points and the length
* of those vectors.
*
* vector v_center_top, length_center_top
* vector v_center_right length_center_right
* vector v_view_center length_view_center
*/
/* local variables */
triple v_view_point;/* from view point to 3D point in question */
double length_view_point; /* length of vector v_view_point */
triple window; /* intersection point of window plane and */
/* the vector v_view_point */
double cosine_theta; /* computed cosine of angle theta */
xy_t screen; /* computed screen x and y points */
double cosine_alpha; /* between v_center_right and v_center_window */
double sine_alpha; /* between v_center_right and v_center_window */
double cosine_beta; /* between v_center_top and v_center_windos */
double dtemp; /* for temporary double */
triple lambda_view_point; /* from view point to 3D point */
triple v_view_window; /* from view point to window intersect*/
double length_view_window; /* length from view to window */
triple v_center_window; /* from center to window intersection */
double length_center_window_squared;
double length_center_window; /* length from center to intersection */
/* code starts here **********************************************/
/* assume point is not in view */
_2D_point->x = 0;
_2D_point->y = 0;
/* compute vector v_view_point: view point to 3D point in question */
VECTORIZE( v_view_point, view_point, _3D_point );
/*
* length of vector v_view_point (check point in question is not EXACTLY
* at the same place as the view point otherwise sqrt will give error)
*/
if ( POINTS_NOT_EQUAL( view_point, _3D_point ) )
{
length_view_point = VECTOR_LENGTH( v_view_point );
}
else
{
return( FALSE );
}
/*
* if length is not more than that from view point to window, ignore
* the point, and exit here because point is not in view
*/
if( length_view_point <= length_view_center )
{
return( FALSE );
}
/*
* compute angle between vector v_view_center and v_view_point
* for angles -90 to +90 cosine_theta is between 0 and 1
* for angles greater than 90 degrees, cosine_theta is negative
*/
if ( (cosine_theta = ( DOT_PRODUCT( v_view_center, v_view_point ) )/
(length_view_point * length_view_center) )
<= cosine_half_field_of_view )
{
/* cosine_theta is less than half of the field
of view, which means the point is not visible on the screen */
return(FALSE);
}
/*
* Point is on the screen, plot it.
*
* compute length along vector v_view_point to its intersection with the
* plane of the window
*/
length_view_window = length_view_center / cosine_theta;
/* unit vector on vector v_view_point is */
UNIT_VECTOR( lambda_view_point, v_view_point, length_view_point );
/* vector view point to the window along the vector v_view_point is */
VECTOR_X_SCALAR( v_view_window, lambda_view_point, length_view_window );
/* window point is view point plus vector v_view_window */
POINT_PLUS_VECTOR( window, view_point, v_view_window );
/* now to find which quadrant on the screen this point is at */
/* vector from center of window to the window point is */
VECTORIZE( v_center_window, window_center, window );
/* length squared of v_center_window */
length_center_window_squared = (v_center_window.x * v_center_window.x)+
(v_center_window.y * v_center_window.y)+
(v_center_window.z * v_center_window.z);
/* compute angle between vectors v_center_window and v_center_right */
if( length_center_window_squared > 0.0 )
{
length_center_window = sqrt( length_center_window_squared );
cosine_alpha=((DOT_PRODUCT(v_center_window, v_center_right ) ) /
(length_center_right * length_center_window) );
cosine_beta=((DOT_PRODUCT( v_center_window, v_center_top ) ) /
(length_center_top * length_center_window) );
}
else /* we have a point directly at screen center */
{
_2D_point->x = screen_center.x;
_2D_point->y = screen_center.y;
return( TRUE );
}
/*
* the two angles alpha and beta are computed to help find the quadrant.
* for quadrant x > 0, y > 0 cos_alpha > 0 and cos_beta > 0
* for quadrant x < 0, y > 0 cos_alpha < 0 and cos_beta > 0
* for quadrant x < 0, y < 0 cos_alpha < 0 and cos_beta < 0
* for quadrant x > 0, y < 0 cos_alpha > 0 and cos_beta < 0
*
* now have an angle and a length on the screen, plot the point
* get the sine from the cosine. ( sin*sin + cos*cos ) = 1
* sin = sqrt( 1 - (cos*cos) )
*/
if ( (dtemp=(cosine_alpha * cosine_alpha)) >= 1.0 )
sine_alpha = 0.0; /* overflow protection */
else /* sometimes cos*cos is slightly over 1.0 by round off error */
sine_alpha = sqrt( 1.0 - dtemp );
if ( cosine_beta < 0.0 ) /* quadrant is where y < 0 */
sine_alpha = - sine_alpha;
/*
* Here as calculated,
* screen.x and .y are the x and y components of the vector v_center_window
* in the screen pixel units based on a coordinate system that is
* a normal x positive to right, y positive up.
*/
screen.x = length_center_window * cosine_alpha / _3D_units_per_ypixel;
screen.y = length_center_window * sine_alpha / _3D_units_per_ypixel;
/*
* convert to coordinate system of the video screen where y is positive
* down.
* (needed when coord system is (0,0) upper left, (maxx, maxy) lower right)
* (NOTE: commented out for CGI)
screen.x = (screen.x * aspect_ratio) + screen_center.x;
screen.y = screen_center.y - screen.y;
*
* In the case of (0,0) lower left and (maxx, maxy) upper right, just
* adjust for aspect ratio. (This is CGI.)
*/
screen.x = screen.x + screen_center.x;
screen.y = screen_center.y + screen.y;
/* final limit checks, just in case. */
if ( (screen.x < 0) || (screen.x > screen_max.x) ||
(screen.y < 0) || (screen.y > screen_max.y) )
{
return(FALSE); /* something went wrong */
}
else
{
_2D_point->x = screen.x;
_2D_point->y = screen.y;
return( TRUE ); /* plot is OK */
}
return( FALSE ); /* should NEVER get to here */
} /* end of plot */